/*
 * Nodo.cpp
 *
 *  Created on: 24/10/2009
 *      Author: julfc
 */

#include "Nodo.h"
#include "Arbol.h"

Nodo::Nodo(short tipo) {
	this->tipo = tipo;
	this->cantClavesUsadas = 0;
	this->cantRegistrosUsados = 0;
	this->numBloque = 0;
	this->siguiente = 0;
	this->claves = new list<string>();
	this->punteros = new list<Referencia>();
	this->registros = new list<RegistroArbol>();
}

Nodo::Nodo() {
	this->cantClavesUsadas = 0;
	this->cantRegistrosUsados = 0;
	this->numBloque = 0;
	this->siguiente = 0;
	this->claves = new list<string>();
	this->punteros = new list<Referencia>();
	this->registros = new list<RegistroArbol>();
}

Nodo::~Nodo() {
	// TODO Auto-generated destructor stub
}

void Nodo::Save(fstream* file, int offset, short raiz, short hoja, short indice) throw (exception) {
	try	{
		file->seekp(offset, ios::beg);
		// Escribo los de control
		file->write((char*)(&(this->tipo)), sizeof(short));
		file->write((char*)(&(this->cantClavesUsadas)), sizeof(int));
		file->write((char*)(&(this->cantRegistrosUsados)), sizeof(int));
		file->write((char*)(&(this->numBloque)), sizeof(int));
		file->write((char*)(&(this->siguiente)), sizeof(int));
		if(this->tipo == raiz) {
			// Escribo las claves
			for(list<string>::iterator i=claves->begin(); i != claves->end(); ++i) {
				string* s = &(*i);
				file->write(s->c_str(), strlen(s->c_str()) );
			}
			// El nodo raiz es; tambien hoja
			if(cantRegistrosUsados > 0) {
				// Escribo los registros
				for(list<RegistroArbol>::iterator j=registros->begin(); j != registros->end(); ++j) {
					RegistroArbol* r = &(*j);
					file->write((char*)(&(r->bloque)), sizeof(int));
					file->write((char*)(&(r->offset)), sizeof(int));
				}
			} else {
				if(cantClavesUsadas > 0) {
					// Escribo los punterosint
					for(list<Referencia>::iterator k=punteros->begin(); k != punteros->end(); ++k) {
						Referencia* p = &(*k);
						file->write((char*)(&(p->bloque)), sizeof(int));
						file->write((char*)(&(p->offset)), sizeof(int));
					}
				}
			}
		} else if(tipo == indice)	{
			if(cantClavesUsadas > 0) {
				// Escribo las claves
				for(list<string>::iterator i=claves->begin(); i != claves->end(); ++i) {
					string* s = &(*i);
					file->write(s->c_str(), strlen(s->c_str()) );
				}
				// Escribo los punteros
				for(list<Referencia>::iterator k=punteros->begin(); k != punteros->end(); ++k) {
					Referencia* p = &(*k);
					file->write((char*)(&(p->bloque)), sizeof(int));
					file->write((char*)(&(p->offset)), sizeof(int));
				}
			}
		} else if(tipo == hoja) {
			if(cantClavesUsadas > 0) {
				// Escribo las claves
				for(list<string>::iterator i=claves->begin(); i != claves->end(); ++i) {
					string* s = &(*i);
					file->write(s->c_str(), strlen(s->c_str()) );
				}
				// Escribo los registros
				for(list<RegistroArbol>::iterator j=registros->begin(); j != registros->end(); ++j) {
					RegistroArbol* r = &(*j);
					file->write((char*)(&(r->bloque)), sizeof(int));
					file->write((char*)(&(r->offset)), sizeof(int));
				}
			}
		}
	} catch(exception e) {
		throw e;
	}
}

Nodo Nodo::Obtener(fstream* file, int offset, short raiz, short hoja, int longClave) throw (exception) {
	try	{
		Nodo nodo;
		file->flush();
		file->seekg(offset, ios::beg);
		//Leo los valores de control
		file->read(reinterpret_cast<char*>(&(nodo.tipo)), sizeof(nodo.tipo));
		file->read(reinterpret_cast<char*>(&(nodo.cantClavesUsadas)), sizeof(nodo.cantClavesUsadas));
		file->read(reinterpret_cast<char*>(&(nodo.cantRegistrosUsados)), sizeof(nodo.cantRegistrosUsados));
		file->read(reinterpret_cast<char*>(&(nodo.numBloque)), sizeof(nodo.numBloque));
		file->read(reinterpret_cast<char*>(&(nodo.siguiente)), sizeof(nodo.siguiente));
		// Leo las claves que son comunes
		char s[20];
		for(int i = 0; i < nodo.cantClavesUsadas; ++i) {
			file->read(s, longClave);
			nodo.claves->push_back(string(s));
		}
		Referencia puntTemp;
		RegistroArbol regTemp;

		if(nodo.tipo == raiz) {
			// Es el unico nodo y actua como hoja tambien
			if(nodo.cantRegistrosUsados > 0) {
				// Leo los registros
				for(int i = 0; i < nodo.cantRegistrosUsados; ++i) {
					file->read(reinterpret_cast<char*>(&(regTemp.bloque)), sizeof(regTemp.bloque));
					file->read(reinterpret_cast<char*>(&(regTemp.offset)), sizeof(regTemp.offset));
					nodo.registros->push_back(regTemp);
				}
			} else {// No es el unico nodo y actua como indice tambien.
				if(nodo.cantClavesUsadas > 0) {// Solo tiene punteros si tiene claves
					// Leo los punteros
					for(int j = 0; j < nodo.cantClavesUsadas + 1; ++j) {
						file->read(reinterpret_cast<char*>(&(puntTemp.bloque)), sizeof(puntTemp.bloque));
						file->read(reinterpret_cast<char*>(&(puntTemp.offset)), sizeof(puntTemp.offset));
						nodo.punteros->push_back(puntTemp);
					}
				}
			}
		} else {
			if(nodo.tipo == hoja) {
				// Leo los registros
				for(int i = 0; i < nodo.cantRegistrosUsados; i++) {
					file->read(reinterpret_cast<char*>(&(regTemp.bloque)), sizeof(regTemp.bloque));
					file->read(reinterpret_cast<char*>(&(regTemp.offset)), sizeof(regTemp.offset));
					nodo.registros->push_back(regTemp);
				}
			} else {
				if(nodo.cantClavesUsadas > 0) { //Si tiene
					// Leo los punteros
					for(int j = 0; j < nodo.cantClavesUsadas + 1; j++) {
						file->read(reinterpret_cast<char*>(&(puntTemp.bloque)), sizeof(puntTemp.bloque));
						file->read(reinterpret_cast<char*>(&(puntTemp.offset)), sizeof(puntTemp.offset));
						nodo.punteros->push_back(puntTemp);
					}
				}
			}
		}
		return (nodo);
	} catch(exception e) {
		throw e;
	}
}
void Nodo::Limpiar() {
	this->cantClavesUsadas = 0;
	this->cantRegistrosUsados = 0;
	this->numBloque = 0;
	this->tipo = 0;
	this->siguiente = 0;
	this->claves->clear();
	this->punteros->clear();
	this->registros->clear();
}
